library IEEE;
   use IEEE.std_logic_1164.all;
   use IEEE.numeric_bit.all;

entity Top_Module is
  port(CLK,RST: in bit; BUS_Data: out unsigned(15 downto 0);
  Led_out1: out std_logic_vector (7 downto 0);
  Led_enout: out std_logic_vector(3 downto 0);
  outputLED: out bit;
  outhighbyte: out unsigned(7 downto 0));
end Top_Module;

architecture model of Top_Module is

component MARMUX_logic is
  port(MARMUX: in bit; ADDR_out,IR_out: in unsigned(15 downto 0);
        MARMUX_out: out unsigned(15 downto 0));
end component;
component SEXT is
   port(IR_out: in unsigned(15 downto 0);
        PCoffset11: out unsigned(15 downto 0);
        PCoffset9: out unsigned(15 downto 0);
        PCoffset8: out unsigned(15 downto 0);
        Imm7: out unsigned(15 downto 0));
end component;
component PCMUX_logic is
   port(Clk: in bit; PCMUX: in  bit_vector(1  downto 0);
        PCval,BUS_in,ADDR_out: in unsigned(15 downto 0);
        PCMUX_out: out unsigned(15 downto 0));
end component;
component ADDR1MUX_logic is
   port(ADDR1MUX: in bit;
        PCval,SR2: in unsigned(15 downto 0);
        ADDR1MUX_out: out unsigned(15 downto 0));
end component;
component SR2MUX_logic is
   port(SR2val: in unsigned(15 downto 0);
        Imm7: in unsigned(15 downto 0);
        IR_out: in unsigned(15 downto 0);
        SR2MUX_out: out unsigned(15 downto 0));
end component;
component SHF is
   port(IR_out:     in unsigned  (15 downto 0);
             A:      in unsigned  (15 downto 0);
             Result: out unsigned (15 downto 0));
end component;
component ALU is
   port(CS: in bit_vector (1 downto 0);
        A, B: in unsigned (15 downto 0);
        Result: out unsigned (15 downto 0));
end component;
component ADDR is
port(ADDR1MUX_out,ADDR2MUX_out: in unsigned(15 downto 0);
        ADDR_out: out unsigned(15 downto 0));
end component;
component IR is
   port(Clk,LD_IR: in  bit;
        BUS_in:    in  unsigned(15 downto 0);
        IR_out:    out unsigned(15 downto 0));
end component;
component PC is
   port(Clk,LD_PC: in  bit;
        PCMUX_out: in  unsigned(15 downto 0);
        PCval:     out unsigned(15 downto 0));
end component;
component ADDR2MUX_logic is
   port(ADDR2MUX: in bit_vector(1 downto 0);
        PCoffset11: in unsigned(15 downto 0);
        PCoffset9: in unsigned(15 downto 0);
        PCoffset8: in unsigned(15 downto 0);
        LSHF1: in bit;
        ADDR2MUX_out: out unsigned(15 downto 0));
end component;
component REGMUX_logic is
   port(SR1val: in unsigned(15 downto 0);
        BUS_in: in unsigned(15 downto 0);
        IR_out: in unsigned(15 downto 0);
        REGMUX: in bit;
        REGMUX_out: out unsigned(15 downto 0));
end component;
component REG is
   port(CLK: in bit; LD_Reg: in bit;
  DR, SR2: in unsigned(3 downto 0); Reg_In: in unsigned(15 downto 0);
          ReadReg1, ReadReg2,ReadReg3,ReadReg4: out unsigned(15 downto 0));
end component;
component DRMUX_logic is
   port(IR_out: in unsigned(15 downto 0);
        DRMUX: in bit_vector(1 downto 0);
        DRMUX_out: out unsigned(3 downto 0));
end component;
component NZP_Logic is
   port(Clk: in bit;
        LD_CC: in bit;
        BUS_in:    in unsigned(15 downto 0);
        N, Z, P: out bit);
end component;
component State_graph is
    port(CLK,RST,Ready,N,Z,P: in bit;
       IR_out: in unsigned(15 downto 0);
       LD_MAR,LD_MDR,LD_IR,LD_BEN,LD_REG,LD_CC,LD_PC: out bit;
       GatePC,GateMDR,GateALU,GateMARMUX,GateSHF: out bit;
       PCMUX,DRMUX,ADDR2MUX,ALUK: out bit_vector(1 downto 0);
       REGMUX,ADDR1MUX,MARMUX,MIO_EN,R_W,DATA_SIZE,LSHF1: out bit;
       Current_State: out integer range 0 to 64;
       outputLED: out bit);
end component;
component Memory_Controller is
    port(Clk,Ld_MAR,Ld_MDR,MIO_EN: in bit; R_W,Mem_En,Data_Size,GateMDR_Cntrl: in bit; 
         Bus_in: in unsigned(15 downto 0);
         GateMDR_Val,MAR_temp,MDR_temp,Mem_temp,MDRin_temp: out unsigned(15 downto 0));
end component;
component Test_Disp is
    Port (clk: in bit;
		--mode : in integer range 0 to 3;
	  led_dig0: in integer range 0 to 15;
	  led_dig1: in integer range 0 to 15;
	  led_dig2: in integer range 0 to 15;
	  led_dig3: in integer range 0 to 15;
  	  led_dig_out : out std_logic_vector(7 downto 0);
  	  led_en_out : out std_logic_vector(3 downto 0));
end component;

-- internal signals
signal ADDR_out,ADDR1_out,ADDR2_out: unsigned(15 downto 0);
signal IR_out: unsigned(15 downto 0);
signal GateALU_val,GateMARMUX_val,GateMDR_val,GatePC_val,GateSHF_val: unsigned(15 downto 0);
signal SEXT11,SEXT9,SEXT8,SEXT7:unsigned(15 downto 0);
signal DRSR1_Val,SR2_Val,LED,RESULT: unsigned(15 downto 0);
signal PC_Val: unsigned(15 downto 0):="0000000000000000";
signal REGMUX_out,SR2MUX_out, PCMUX_out:unsigned(15 downto 0);
signal DRSR1,SR2: unsigned(3 downto 0);
signal N_out,Z_out,P_out: bit;

signal Ready: bit;
signal Mem_En: bit:='1';
signal Bus_in: unsigned(15 downto 0):="0000000000000000";
----------------
signal CurrState: integer range 0 to 64;
signal MAR_out,MDR_out,Mem_out,MDR_in: unsigned(15 downto 0);

-- control signals
signal LD_MAR,LD_MDR,LD_IR,LD_BEN,LD_REG,LD_CC,LD_PC: bit;
signal GatePC,GateMDR,GateALU,GateMARMUX,GateSHF: bit;
signal DRMUX,ADDR2MUX,ALUK: bit_vector(1 downto 0);
signal PCMUX:bit_vector(1 downto 0);
signal REGMUX,ADDR1MUX,MARMUX,MIO_EN,R_W,DATA_SIZE,LSHF1: bit;

begin 
SR2 <= IR_out(6 downto 3);
outhighbyte <= Result(15 downto 8);
Ready <= '1';
    
    
process(GatePC,GateMDR,GateALU,GateMARMUX,GateSHF,
        PC_val,GateMDR_val,GateALU_val,GateMARMUX_val,GateSHF_val)--,Clk)
    begin
  --if Clk = '1' and Clk'event then
      if    GatePC = '1' then Bus_in <= PC_val ;--after 1 ns;
      elsif GateMDR = '1' then Bus_in <= GateMDR_val;-- after 1 ns;
      elsif GateALU = '1' then Bus_in <= GateALU_val ;--after 1 ns;
      elsif GateMARMUX = '1' then Bus_in <= GateMARMUX_val ;--after 1 ns;
      elsif GateSHF = '1' then Bus_in <= GateSHF_val ;--after 1 ns;
     end if;
   --end if;
    end process;
    
 --   Bus_in <= GatePC_val when GatePC = '1'
 --   else
 --   GateMDR_val when GateMDR = '1'
  --  else
 --   GateALU_val when GateALU = '1'
--   else
  --   GateMARMUX_val when GateMARMUX = '1'
 --   else
 --    GateSHF_val when GateSHF = '1'
  --   else "0000000000000000";

        
    MAR: MARMUX_logic port map(MARMUX,ADDR_out,IR_out,GateMARMUX_val);
    SGN: SEXT port map(IR_out,SEXT11,SEXT9,SEXT8,SEXT7);
    PCM: PCMUX_logic port map(Clk,PCMUX,PC_Val,Bus_in,ADDR_out,PCMUX_out);
    ADR: ADDR port map(ADDR1_out,ADDR2_out,ADDR_out);
    AD1: ADDR1MUX_logic port map(ADDR1MUX,PC_Val,SR2_Val,ADDR1_out);
    AD2: ADDR2MUX_logic port map(ADDR2MUX,SEXT11,SEXT9,SEXT8,LSHF1,ADDR2_out);
    SRX: SR2MUX_logic port map(SR2_Val,SEXT7,IR_out,SR2MUX_out);
    SHT: SHF port map(IR_out,DRSR1_Val,GateSHF_val);
    ALX: ALU port map(ALUK,DRSR1_Val,SR2MUX_out,GateALU_val);
    IRX: IR port map(CLK,LD_IR,Bus_in,IR_out);
    PCX: PC port map(CLK,LD_PC,PCMUX_out,PC_Val);
    RGM: REGMUX_logic port map(DRSR1_Val,Bus_in,IR_out,REGMUX,REGMUX_out);
    RGX: REG port map(CLK,LD_REG,DRSR1,SR2,REGMUX_out,DRSR1_Val,SR2_Val,RESULT,LED);
    DRM: DRMUX_logic port map(IR_out,DRMUX,DRSR1);
    NZP: NZP_Logic port map(CLK,LD_CC,Bus_in,N_out,Z_out,P_out);
    STG: State_Graph port map(Clk,RST,Ready,N_out,Z_out,P_out,IR_out,
          LD_MAR,LD_MDR,LD_IR,LD_BEN,LD_REG,LD_CC,LD_PC,
          GatePC,GateMDR,GateALU,GateMARMUX,GateSHF,
          PCMUX,DRMUX,ADDR2MUX,ALUK,
          REGMUX,ADDR1MUX,MARMUX,MIO_EN,R_W,DATA_SIZE,LSHF1,
          CurrState,outputLED);
    MMC: Memory_Controller port map(Clk,Ld_MAR,Ld_MDR,MIO_EN,R_W,Mem_EN,DATA_SIZE,GateMDR,
          Bus_in,GateMDR_Val,MAR_out,MDR_out,Mem_out,MDR_in);
    TDP: Test_Disp port map(Clk,to_integer(Result(3 downto 0)),
    to_integer(Result(7 downto 4)),to_integer(Result(11 downto 8)),
    to_integer(Result(15 downto 12)),Led_out1,Led_enout);
    
BUS_Data <= Bus_in;
end model;